package com.micro.platform.oauth.config.oauth.grant;

import com.micro.platform.oauth.component.CaptchaComponent;
import com.micro.platform.oauth.domain.LocalClientDetails;
import com.micro.platform.oauth.framework.domain.ClientDetails;
import com.micro.platform.oauth.framework.domain.OauthContext;
import com.micro.platform.oauth.framework.domain.OauthRequest;
import com.micro.platform.oauth.framework.domain.UserDetails;
import com.micro.platform.oauth.framework.interfaces.IClientDetailsService;
import com.micro.platform.oauth.framework.interfaces.ITokenGranter;
import com.micro.platform.oauth.framework.interfaces.IUserDetailsService;
import com.micro.platform.starter.component.PasswordEncoderComponent;
import com.micro.platform.starter.utils.AssertUtil;
import com.micro.platform.starter.utils.MapUtils;
import com.micro.platform.starter.utils.NumberUtils;
import lombok.extern.slf4j.Slf4j;

import java.security.NoSuchAlgorithmException;

@Slf4j
public class PasswordTokenGranter implements ITokenGranter {

    public static final String GRAPH_ID = "graphId";
    public static final String PUBLIC_KEY = "publicKey";

    private String grantType = "password";
    private IClientDetailsService clientDetailsService;
    private IUserDetailsService userDetailsService;
    private PasswordEncoderComponent passwordEncoderComponent;
    private CaptchaComponent captchaComponent;


    public PasswordTokenGranter(IClientDetailsService clientDetailsService, IUserDetailsService userDetailsService, PasswordEncoderComponent passwordEncoderComponent, CaptchaComponent captchaComponent) {
        this.clientDetailsService = clientDetailsService;
        this.userDetailsService = userDetailsService;
        this.passwordEncoderComponent = passwordEncoderComponent;
        this.captchaComponent = captchaComponent;
    }

    @Override
    public OauthContext grant(OauthRequest request) {
        String clientId = request.getClientId();
        String account = request.getAccount();
        String password = request.getPassword();
        String clientSecret = request.getClientSecret();
        String graphId = MapUtils.getString(request.getRequestParam(), GRAPH_ID);
        String publicKey = MapUtils.getString(request.getRequestParam(), PUBLIC_KEY);
        AssertUtil.notEmptyString(graphId, "图形ID不能为空");
        ClientDetails clientDetails = this.clientDetailsService.loadClientDetailsByClientId(clientId);
        AssertUtil.notNull(clientDetails, "客户端不存在");
        AssertUtil.isTrue(clientDetails.getClientSecret().equals(clientSecret), "客户端密钥错误");
        LocalClientDetails clientDetails1 = (LocalClientDetails) clientDetails;
        Integer secretKeyType = clientDetails1.getSecretKeyType();
        if(NumberUtils.equalsInteger(0, secretKeyType)){
            clientDetails1.setPublicKey(publicKey);
        }
        AssertUtil.notEmptyString(clientDetails1.getPublicKey(), "客户端公钥不能为空");
        UserDetails userDetails = this.userDetailsService.loadUserDetailsByAccount(account);
        AssertUtil.notNull(userDetails, "用户不存在");
        String captcha = captchaComponent.getCaptcha(graphId);
        AssertUtil.notEmptyString(captcha, "验证码已失效");
        log.info("password:{}, user:{}, captchaValidateCode:{}",password, userDetails.getPassword(), captcha.toUpperCase());
        try {
            AssertUtil.isTrue(passwordEncoderComponent.matches(password, userDetails.getPassword(), captcha.toUpperCase()),"验证码或密码不正确");
        } catch (NoSuchAlgorithmException e) {
            AssertUtil.error("验证码或密码不正确");
        }
        captchaComponent.removeCaptcha(graphId);
        OauthContext oauthContext = new OauthContext(userDetails, request, clientDetails);
        return oauthContext;
    }

    @Override
    public String getGrantType() {
        return grantType;
    }
}
